package com.gaotai.wangfei.exam.ioc.service.bean;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.gaotai.wangfei.exam.ioc.config.Bean;
import com.gaotai.wangfei.exam.ioc.config.Property;
import com.gaotai.wangfei.exam.ioc.parse.ConfigManager;
import com.gaotai.wangfei.exam.ioc.service.BeanFactory;
import com.gaotai.wangfei.exam.util.StringUtils;

/**
 * 
 * <p>
 * Description: [bean工厂的实现类]
 * </p>
 * 
 * @author <a href="mailto: wangfei@gaotai.cn">王飞</a>
 * @version $Revision$
 */
public class ClassPathXmlApplicationContext implements BeanFactory
{
	//xml中bean的配置map
	private Map<String, Bean> configMap;

	//容器的实例化出来的bean的map
	private Map<String, Object> context = new HashMap<String, Object>();

	@Override
	public Object getBean(String beanName)
	{
		return context.get(beanName);
	}

	/**
	 * 
	 * <p>
	 * [bean工厂的够造化]
	 * </p>
	 * 
	 * @coustructor 方法.
	 */
	public ClassPathXmlApplicationContext(String path)
	{
		//获得配置的map
		configMap = ConfigManager.getConfig(path);
		//遍历map初始化bean
		if(configMap != null)
		{
			for (Entry<String, Bean> entry : configMap.entrySet())
			{
				String beanName = entry.getKey();
				Bean bean = entry.getValue();
				Object existBean = context.get(beanName);
				if(existBean == null)
				{
					Object beanObj = createBean(bean);
					context.put(beanName, beanObj);
				}
			}
		}

	}

	/**
	 * 
	 * <p>
	 * 根据Bean配置创建Bean实例
	 * </p>
	 * 
	 * @param bean
	 * @return
	 * @author:wangfei 2016-3-18
	 * @update: [updatedate] [changer][change description]
	 */
	private Object createBean(Bean bean)
	{
		if(bean != null)
		{
			//bean的类名
			String className = bean.getClassName();
			Class clazz = null;
			try
			{
				clazz = Class.forName(className);
			}
			catch (ClassNotFoundException e)
			{
				e.printStackTrace();
				throw new RuntimeException("请检查bean的class是否配置正确!");
			}
			//创建相关的类
			Object beanObj = null;
			try
			{
				beanObj = clazz.newInstance();
			}
			catch (Exception e)
			{
				e.printStackTrace();
				throw new RuntimeException("请检查您的bean的时候含有空的构造参数!");
			}
			//对于bean的properties的属性注入
			if(bean.getProperties() != null && !bean.getProperties().isEmpty())
			{
				for (Property property : bean.getProperties())
				{
					//对于property的value的属性注入
					if(property.getValue() != null && !property.getValue().isEmpty())
					{
						String value = property.getValue().get(0);
						String name = property.getName();
						//apache提供的属性自动注入(自动判断属性的类型)
						if(!StringUtils.isNullString(value))
						{
							Map<String, String[]> paramMap = new HashMap<String, String[]>();
							paramMap.put(name, new String[]{value});
							try
							{
								org.apache.commons.beanutils.BeanUtils.populate(beanObj, paramMap);
							}
							catch (Exception e)
							{
								e.printStackTrace();
								throw new RuntimeException("您的bean的属性" + name + "没有相对应的set方法，或者方法参数不正确" + className);
							}
						}
						//						2.自己实现的属性注入
						//						Method setMethod = BeanUtils.getWriteMethod(beanObj, name);
						//						try
						//						{
						//							setMethod.invoke(beanObj, value);
						//						}
						//						catch (Exception e)
						//						{
						//							// TODO Auto-generated catch block
						//							e.printStackTrace();
						//							throw new RuntimeException("您的bean的属性" + name + "没有相对应的set方法，或者方法参数不正确" + className);
						//						}
					}
					
					//对于property的拦截器链的属性注入
					if(property.getInterceptorList() != null && !property.getInterceptorList().isEmpty())
					{
						List<Object> interceptorList = new ArrayList<Object>();
						for (String interceptor : property.getInterceptorList())
						{
							Object existBean = context.get(interceptor);
							if(existBean == null)
							{
								existBean = createBean(configMap.get(interceptor));
								context.put(interceptor, existBean);
							}
							interceptorList.add(existBean);
						}
						String name = property.getName();

						//apache提供的属性自动注入(不用判断属性的类型)
						if(!interceptorList.isEmpty())
						{
							Map<String, List<Object>> paramMap = new HashMap<String, List<Object>>();
							paramMap.put(name, interceptorList);
							try
							{
								org.apache.commons.beanutils.BeanUtils.populate(beanObj, paramMap);
							}
							catch (Exception e)
							{
								e.printStackTrace();
								throw new RuntimeException("您的bean的属性" + name + "没有相对应的set方法，或者方法参数不正确" + className);
							}
						}
					}
				}

			}
			//获得bean的属性将其注入
			return beanObj;
		}
		else
		{

			return null;
		}

	}
}
